﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media;
using System.Windows;
using System.Windows.Controls;

namespace RentAWorker.Management.Infrastructure
{
    public class RadialPanel : Panel
    {
        double _maxChildHeight, _perimeter, _radius, _fudgeFactor;

        protected override Size MeasureOverride(Size availableSize)
        {
            _perimeter = 0;
            _maxChildHeight = 0;

            foreach (UIElement uie in Children)
            {
                uie.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
                _perimeter += uie.DesiredSize.Width;
                _maxChildHeight = Math.Max(_maxChildHeight, uie.DesiredSize.Height);
            }

            //If the marginal angle is not 0, 90 or 180
            //then the fudge factor is needed.
            if (Children.Count > 2 && Children.Count != 4)
                _fudgeFactor = 10;
            //Determine the radius of the circle layout and determine
            //the RadialPanel's DesiredSize.
            _radius = _perimeter / (2 * Math.PI) + _fudgeFactor;

            double _squareSize = 2 * (_radius + _maxChildHeight);
            return new Size(_squareSize, _squareSize);
        }

        //Perform arranging of children based on 
        //the final size.
        protected override Size ArrangeOverride(Size finalSize)
        {
            //Necessary variables.
            double _currentOriginX = 0,
                    _currentOriginY = 0,
                    _currentAngle = 0,
                    _centerX = 0,
                    _centerY = 0,
                    _marginalAngle = 0;

            //During measure, a fudge factor was added to the radius
            //to account for rotated children that might fall outside
            //of the desired size.  Now, during arrange, we don't need
            //that extra space.
            _radius -= _fudgeFactor;

            //Find center of the circle based on arrange size.
            //DesiredSize is not used because the panel
            //is potentially being arranged across a larger
            //area from the default alignment values.
            _centerX = finalSize.Width / 2;
            _centerY = finalSize.Height / 2;

            //Determine the marginal angle, the angle between
            //each child on the circle.
            if (Children.Count != 0)
                _marginalAngle = 360 / Children.Count;

            foreach (UIElement uie in Children)
            {
                //Find origin from which to arrange on
                //each child of the RadialPanel (its top
                //left corner.)
                _currentOriginX = _centerX - uie.DesiredSize.Width / 2;
                _currentOriginY = _centerY - _radius - uie.DesiredSize.Height;

                //Apply a rotation on each child around the center of the
                //RadialPanel.
                var center = new Point(uie.DesiredSize.Width / 2, uie.DesiredSize.Height + _radius);
                uie.RenderTransform = new RotateTransform(_currentAngle, center.X, center.Y);
                uie.Arrange(new Rect(new Point(_currentOriginX, _currentOriginY), new Size(uie.DesiredSize.Width, uie.DesiredSize.Height)));

                //Increment the _currentAngle by the _marginalAngle
                //to advance the next child to the appropriate position.
                _currentAngle += _marginalAngle;
            }

            //In this case, the Panel is sizing to the space
            //given, so, return the finalSize which will be used
            //to set the ActualHeight & ActualWidth and for rendering.
            return finalSize;
        }
    }
}
